package com.john.test.fictiongetter;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;

/**
 * @author jiangguangtao on 2016/9/13.
 */
public class SimpleFictionGetter {
    private static final Logger LOGGER = LoggerFactory.getLogger(SimpleFictionGetter.class);
    private String baseUri;
    private String beginUri;
    private String endUri;
    private String titlePreRemove;
    private String titlePostRemove = "都市神级高手-乐文小说网";

    public SimpleFictionGetter(String baseUri, String beginUri, String endUri) {
        this.baseUri = baseUri;
        this.beginUri = beginUri;
        this.endUri = endUri;
    }

    /**
     * 输出
     *
     * @param outputStream
     * @param charset
     */
    public void doOutput(OutputStream outputStream, Charset charset) {
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, charset));


        try {
            boolean runFlag = true;

            String pageUri = beginUri;
            while (runFlag) {
                FictionPager fp = getPagger(pageUri);
                if (!StringUtils.isBlank(fp.getContent())) {
                    appendTxt(writer, fp);
                }
                if (fp.isEnd()) {
                    runFlag = false;
                }
                pageUri = fp.getNextUrl();
            }
        } catch (IOException e) {
            LOGGER.error("输出错误了", e);
        } finally {
            try {
                writer.flush();
                writer.close();
            } catch (IOException e) {

            }
        }


    }

    /**
     * 追加内容到输出流中
     *
     * @param writer
     * @param fp
     * @throws IOException
     */
    private void appendTxt(BufferedWriter writer, FictionPager fp) throws IOException {
        writer.write(fp.getTitle());
        writer.newLine();
        String[] lines = fp.getContent().split("\\s+");
        for (String str : lines) {
            writer.write(StringUtils.trimToEmpty(str));
            writer.newLine();
        }
        writer.flush();
    }

    /**
     * 获取一页内容
     *
     * @param beginUri
     * @return
     * @throws IOException
     */
    private FictionPager getPagger(String beginUri) throws IOException {
        FictionPager fp = null;
        String url = baseUri + beginUri;
        LOGGER.info("当前页：{}", url);
        Document document = getDocument(url, 1, 100);
        if(null == document) {
            LOGGER.warn("未获取到内容");
            return new FictionPager(true);
        }
        String title = trimTitle(document.title());
        LOGGER.info("标题：{}", title);

        Element content = document.select("#contents").first();
        if (null == content) {
            LOGGER.warn("未发文档内容");
            return new FictionPager(true);
        }
//        Element p = content.select("p").first();
//        if (null == p) {
//            LOGGER.warn("未发文档内容");
//            return new FictionPager(true);
//        }
        String ftext = content.text();
        LOGGER.debug("当前页文档内容!\n{}", ftext);
        fp = new FictionPager(title, ftext);

//        Element thumb = document.select("#thumb").first();
//        if (null == thumb) {
//            LOGGER.error("未发现导航链接区域");
//            return new FictionPager(true);
//        }

//        Element nextPageLink = thumb.child(2);
        Element nextPageLink = document.select(".readbutton>.readdown a").first();;
        if (null == nextPageLink) {
            LOGGER.error("未发现下一页");
            fp.setEnd(true);
            return fp;
        }

        String nextLink = nextPageLink.attr("href");
        LOGGER.info("下一页是：{}", nextLink);
        if (StringUtils.equalsIgnoreCase(endUri, nextLink)) {
            LOGGER.info("结束获取");
            fp.setEnd(true);
        }

        fp.setNextUrl(nextLink);
        return fp;
    }

    private Document getDocument(String url, int times, long delay) throws IOException {
        if (times > 1) {
            LOGGER.info("第{}次获取:{}", times, url);
        }
        Document document = Jsoup.connect(url).get();
        if (delay > 1) {
            try {
                Thread.sleep(delay);
            } catch (InterruptedException e) {
            }
        }

        String title = trimTitle(document.title());
        LOGGER.info("标题：{}", title);

        Element content = document.select("#contents").first();
        if (null == content) {
            if (times < 7) {
                delay = delay + 800;
                times++;
                return getDocument(url, times, delay);
            } else {
                return null;
            }
        } else {
            return document;
        }
    }

    /**
     * 处理标题
     *
     * @param title
     * @return
     */
    private String trimTitle(String title) {
        if (StringUtils.isNotBlank(titlePreRemove)) {
            title = StringUtils.removeStart(title, titlePostRemove);
        }
        if (StringUtils.isNotBlank(titlePostRemove)) {
            title = StringUtils.removeEnd(title, titlePostRemove);
        }
        return StringUtils.trimToEmpty(title);
    }


    /**
     * Getter for property 'baseUri'.
     *
     * @return Value for property 'baseUri'.
     */
    public String getBaseUri() {
        return baseUri;
    }

    /**
     * Setter for property 'baseUri'.
     *
     * @param baseUri Value to set for property 'baseUri'.
     */
    public void setBaseUri(String baseUri) {
        this.baseUri = baseUri;
    }

    /**
     * Getter for property 'beginUri'.
     *
     * @return Value for property 'beginUri'.
     */
    public String getBeginUri() {
        return beginUri;
    }

    /**
     * Setter for property 'beginUri'.
     *
     * @param beginUri Value to set for property 'beginUri'.
     */
    public void setBeginUri(String beginUri) {
        this.beginUri = beginUri;
    }

    /**
     * Getter for property 'endUri'.
     *
     * @return Value for property 'endUri'.
     */
    public String getEndUri() {
        return endUri;
    }

    /**
     * Setter for property 'endUri'.
     *
     * @param endUri Value to set for property 'endUri'.
     */
    public void setEndUri(String endUri) {
        this.endUri = endUri;
    }

    /**
     * Getter for property 'titlePreRemove'.
     *
     * @return Value for property 'titlePreRemove'.
     */
    public String getTitlePreRemove() {
        return titlePreRemove;
    }

    /**
     * Setter for property 'titlePreRemove'.
     *
     * @param titlePreRemove Value to set for property 'titlePreRemove'.
     */
    public void setTitlePreRemove(String titlePreRemove) {
        this.titlePreRemove = titlePreRemove;
    }

    /**
     * Getter for property 'titlePostRemove'.
     *
     * @return Value for property 'titlePostRemove'.
     */
    public String getTitlePostRemove() {
        return titlePostRemove;
    }

    /**
     * Setter for property 'titlePostRemove'.
     *
     * @param titlePostRemove Value to set for property 'titlePostRemove'.
     */
    public void setTitlePostRemove(String titlePostRemove) {
        this.titlePostRemove = titlePostRemove;
    }

}
